// ex31dDoc.cpp : implementation of the CEx31dDoc class
//

#include "stdafx.h"
#include "ex31d.h"

#include "ex31dDoc.h"
#include "MainFrm.h"
#include "TableSel.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CEx31dDoc

IMPLEMENT_DYNCREATE(CEx31dDoc, CDocument)

BEGIN_MESSAGE_MAP(CEx31dDoc, CDocument)
	//{{AFX_MSG_MAP(CEx31dDoc)
    ON_COMMAND(IDC_REQUERY, OnRequery)
    ON_UPDATE_COMMAND_UI(IDC_REQUERY, OnUpdateRequery)
	ON_COMMAND(ID_FILE_ODBCCONNECT, OnFileOdbcConnect)
	ON_UPDATE_COMMAND_UI(ID_FILE_ODBCCONNECT, OnUpdateFileOdbcConnect)
	ON_COMMAND(ID_FILE_ODBCDISCONNECT, OnFileOdbcDisconnect)
	ON_UPDATE_COMMAND_UI(ID_FILE_ODBCDISCONNECT, OnUpdateFileOdbcDisconnect)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSave)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CEx31dDoc construction/destruction

CEx31dDoc::CEx31dDoc()
{
    m_bConnected = FALSE;
    m_pRecordset = NULL;
    m_nFields = 0;
    m_nRowCount = 0;
}

CEx31dDoc::~CEx31dDoc()
{
}

BOOL CEx31dDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;
    m_strConnect.Empty(); // in case we're SDI
    m_strQuery.Empty();
	return TRUE;
}



/////////////////////////////////////////////////////////////////////////////
// CEx31dDoc serialization

void CEx31dDoc::Serialize(CArchive& ar)
{
    if (ar.IsStoring()) {
     	ar << m_strConnect << m_strQuery;
    }
    else {
    	ar >> m_strConnect >> m_strQuery;
    }
}

/////////////////////////////////////////////////////////////////////////////
// CEx31dDoc diagnostics

#ifdef _DEBUG
void CEx31dDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CEx31dDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CEx31dDoc commands

BOOL CEx31dDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
	if (!CDocument::OnOpenDocument(lpszPathName))
		return FALSE;
    PutQuery();
	OpenOdbc();
	return TRUE;
}

void CEx31dDoc::OnCloseDocument() 
{
    m_strQuery.Empty();
    PutQuery();
    if (m_bConnected) {
      delete m_pRecordset; // destructor calls Close
      m_database.Close();
      m_bConnected = FALSE;
      m_pRecordset = NULL;
	  m_nRowCount = 0;
    }
	CDocument::OnCloseDocument();
}

void CEx31dDoc::GetQuery()
{    // get SQL string from dialog bar
	char text[201];   
    CDialogBar& rBar = ((CMainFrame*) AfxGetApp()->m_pMainWnd)->m_wndQueryBar;
    rBar.GetDlgItemText(IDC_QUERY, text, 200);
	TRACE("GetQuery - text = %s\n", text);
    m_strQuery = text;
}

void CEx31dDoc::PutQuery()
{    // write SQL string to dialog bar
    CDialogBar& rBar = ((CMainFrame*) AfxGetApp()->m_pMainWnd)->m_wndQueryBar;
    rBar.SetDlgItemText(IDC_QUERY, m_strQuery);
}

void CEx31dDoc::GetFieldSpecs()
{
	m_nFields = (int) m_pRecordset->GetODBCFieldCount();
	m_arrayFieldName.SetSize(m_nFields);
	m_arrayFieldSize.SetSize(m_nFields);
	CODBCFieldInfo fi;
	for(int i = 0; i < m_nFields; i++) {
		m_pRecordset->GetODBCFieldInfo(i, fi);
		m_arrayFieldName[i] = fi.m_strName;
		if(fi.m_nSQLType == SQL_DATE) {
			m_arrayFieldSize[i] = 15;
		}
		else {
			m_arrayFieldSize[i] = (short) max(min((short) fi.m_nPrecision, 50),
								fi.m_strName.GetLength());
		}
		TRACE("field name = %s, type = %d, precision = %d, scale = %d\n",
			fi.m_strName, fi.m_nSQLType, fi.m_nPrecision, fi.m_nScale);
	}
}

void CEx31dDoc::OnRequery()
{ 
    GetQuery();
    // Requery won't work because we're changing the SQL statement
    BeginWaitCursor();
	if(m_pRecordset->IsOpen()) {
		m_pRecordset->Close();
	}
    try {	
      m_pRecordset->Open(CRecordset::dynaset, m_strQuery, CRecordset::readOnly);
    }
    catch (CDBException* pe) {
	  AfxMessageBox(pe->m_strError);
	  m_nRowCount = 0;
      UpdateAllViews(NULL);
      EndWaitCursor();
      pe->Delete();
      return;
    }
    if (!m_pRecordset->IsBOF()) {
		while(!m_pRecordset->IsEOF()) {
			m_pRecordset->MoveNext(); // to validate record count
		}
    }	
    m_nRowCount = m_pRecordset->GetRecordCount() + 1;
    TRACE("m_nRowCount = %d\n", m_nRowCount);
    GetFieldSpecs();
    UpdateAllViews(NULL); 
    EndWaitCursor();
}

/////////////////////////////////////////////////////////////////////////////
void CEx31dDoc::OnUpdateRequery(CCmdUI* pCmdUI)
{
    pCmdUI->Enable(m_bConnected);
}

void CEx31dDoc::OnFileOdbcConnect()
{
	m_strConnect.Empty();
    m_strQuery.Empty();
	OpenOdbc();
}

void CEx31dDoc::OpenOdbc()
{
    // can't open ODBC via Access driver
    if (m_strConnect.IsEmpty()) {
      m_strConnect = "ODBC;";
    }
    BeginWaitCursor();
	BOOL bRet;
    try {
      // non-exclusive, read-only, no cursor library (dynaset)
        bRet = m_database.Open("", FALSE, TRUE, m_strConnect, FALSE);
//		bRet = m_database.OpenEx(m_strConnect, CDatabase::openReadOnly);
   }
    catch (CDBException* pe) {
	  AfxMessageBox(pe->m_strError);
      EndWaitCursor();
      pe->Delete();
      return;
    }
	if(bRet) {
		m_strConnect = m_database.GetConnect();
		TRACE("connect = %s\n", m_strConnect);
		OpenRecordset();
	}
    EndWaitCursor();
}

// helper used by OnFileOdbcConnect
void CEx31dDoc::OpenRecordset()
{
    GetQuery();
	if (m_strQuery.IsEmpty()) {
      CTableSelect tableDlg(&m_database);
      if (tableDlg.DoModal() != IDOK) {
        m_database.Close();  // escape route
        return;
      }
	   m_strQuery.Format("select * from [%s]", tableDlg.m_strSelection);
	  PutQuery();
    }

    m_pRecordset = new CRecordset(&m_database);
    try {	
      m_pRecordset->Open(CRecordset::dynaset, m_strQuery, CRecordset::readOnly);
    }
    catch (CDBException* pe) {
	  AfxMessageBox(pe->m_strError);
      UpdateAllViews(NULL);
      m_bConnected = FALSE;
      pe->Delete();
      return;
    }
	if (!m_pRecordset->IsBOF()) {
		while(!m_pRecordset->IsEOF()) {
			m_pRecordset->MoveNext(); // to validate record count
		}
	}
	m_nRowCount = m_pRecordset->GetRecordCount() + 1;
    TRACE("m_nRowCount = %d\n", m_nRowCount);
    GetFieldSpecs();
    UpdateAllViews(NULL);
    m_bConnected = TRUE;
}

void CEx31dDoc::OnUpdateFileOdbcConnect(CCmdUI* pCmdUI)
{
    pCmdUI->Enable(!m_bConnected);
}

void CEx31dDoc::OnUpdateFileSave(CCmdUI* pCmdUI)
{
    pCmdUI->Enable(!m_bConnected);
}

 
void CEx31dDoc::OnFileOdbcDisconnect() 
{
   if (m_bConnected) {
      delete m_pRecordset; // destructor calls Close
      m_database.Close();
      m_bConnected = FALSE; 
      m_pRecordset = NULL;
	  m_nRowCount = 0;
	  UpdateAllViews(NULL);
    }
}

void CEx31dDoc::OnUpdateFileOdbcDisconnect(CCmdUI* pCmdUI)
{
    pCmdUI->Enable(m_bConnected);
}
